using System;
using System.Collections.Generic;
using Microsoft.Xna.Framework;
using Microsoft.Xna.Framework.Audio;
using Microsoft.Xna.Framework.Content;
using Microsoft.Xna.Framework.GamerServices;
using Microsoft.Xna.Framework.Graphics;
using Microsoft.Xna.Framework.Input;
using Microsoft.Xna.Framework.Net;
using Microsoft.Xna.Framework.Storage;
using System.IO;

namespace TileSetRender
{
    /// <summary>
    /// This is the main type for your game
    /// </summary>
    public class Game1 : Microsoft.Xna.Framework.Game
    {
        GraphicsDeviceManager graphics;
        SpriteBatch spriteBatch;
        SpriteFont arial;

        MouseState lastMouseState;

        List<TileSetTile> clickedTiles;
        RenderTarget2D renderTarget;
        R8Parser r8Parser;
        R16Parser r16Parser;
        Map map;
        Vector2 offset = new Vector2(0);
        const float scale = 1.0f;

        const string mapFilePath = @"C:\Users\UserName\Documents\Dune\Working Directory\missions\A5V1.map";
        const string palette = @"C:\Users\UserName\Documents\Dune\Working Directory\Data\bin\PALETTE.BIN";
        const string tilesetFilePath = @"C:\Users\UserName\Documents\Dune\Working Directory\Data\BLOXTREE";
        const string tilesetDataFilePath = @"C:\Users\UserName\Documents\Dune\Working Directory\Data\Bin\TILEATR1.BIN";
        const int tileIndexToCreate = 553;
        const int specialIndexToCreate = 0;

        TileSetDataFile dataFile;
        public Game1()
        {
            graphics = new GraphicsDeviceManager(this);
            Content.RootDirectory = "Content";
            Components.Add(new FrameRateCounter(this));
            Window.AllowUserResizing = true;
        }

        /// <summary>
        /// Allows the game to perform any initialization it needs to before starting to run.
        /// This is where it can query for any required services and load any non-graphic
        /// related content.  Calling base.Initialize will enumerate through any components
        /// and initialize them as well.
        /// </summary>
        protected override void Initialize()
        {
            // TODO: Add your initialization logic here
            graphics.PreferredBackBufferWidth = 1260;
            graphics.PreferredBackBufferHeight = 720 ;
            graphics.ApplyChanges();
            IsMouseVisible = true;
            base.Initialize();
        }

        /// <summary>
        /// LoadContent will be called once per game and is the place to load
        /// all of your content.
        /// </summary>
        protected override void LoadContent()
        {
            // Create a new SpriteBatch, which can be used to draw textures.
            spriteBatch = new SpriteBatch(GraphicsDevice);
            r8Parser = new R8Parser(tilesetFilePath + ".R8", palette, graphics.GraphicsDevice);
            r16Parser = new R16Parser(tilesetFilePath + ".R16", graphics.GraphicsDevice);
            map = new Map(mapFilePath);
            //map = new Map(@"K:\Dune1999\Dune 2000\Dune2000\missions\A1V1.MAP");
            clickedTiles = new List<TileSetTile>();
            arial = Content.Load<SpriteFont>("Arial");
            // TODO: use this.Content to load your game content here
            //Map.RenderToFile(map, r16Parser, "C:/test.jpg");

            dataFile = new TileSetDataFile(tilesetDataFilePath);

        }

        /// <summary>
        /// UnloadContent will be called once per game and is the place to unload
        /// all content.
        /// </summary>
        protected override void UnloadContent()
        {
            return;
            // TODO: Unload any non ContentManager content here
            FileStream fs = File.Create(mapFilePath);
            BinaryWriter bw = new BinaryWriter(fs);
            bw.Write(map.Width);
            bw.Write(map.Height);

            foreach (MapTile mapTile in map.TileArray)
            {
                bw.Write(mapTile.tileIndex);
                bw.Write(mapTile.specialIndex);
            }
            

            /*foreach(TileSetTile tile in clickedTiles)
            {
                foreach(byte attribute in tile.header)
                {
                    bw.Write(attribute);
                }

            }            */
            bw.Close();
            fs.Close();
            
            /*fs = File.Create(mapFilePath + "2");
            bw = new BinaryWriter(fs);
            bw.Write((ushort)150);
            bw.Write((ushort)150);

            for (int i = 0; i < 150; i++)
            {
                for(int j=0;j<150; j++)
                {
                    bw.Write((ushort)49);
                    bw.Write((ushort)0);
                }
            }
            
            bw.Close();
            fs.Close();*/
             
             
        }

        /// <summary>
        /// Allows the game to run logic such as updating the world,
        /// checking for collisions, gathering input, and playing audio.
        /// </summary>
        /// <param name="gameTime">Provides a snapshot of timing values.</param>
        protected override void Update(GameTime gameTime)
        {
            // Allows the game to exit
            if (GamePad.GetState(PlayerIndex.One).Buttons.Back == ButtonState.Pressed)
                this.Exit();
            if (Keyboard.GetState().IsKeyDown(Keys.Left))
                offset.X+=5;
            if (Keyboard.GetState().IsKeyDown(Keys.Right))
                offset.X-=5;
            if (Keyboard.GetState().IsKeyDown(Keys.Up))
                offset.Y+=5;
            if (Keyboard.GetState().IsKeyDown(Keys.Down))
                offset.Y-=5;
            
            
            
            //dataFile

            //if (IsActive)
            //{
            //    if (currentTile.X >= 0 && currentTile.Y >= 0 && currentTile.X < map.Width && currentTile.Y < map.Height)
            //    {
            //        if (Mouse.GetState().LeftButton == ButtonState.Pressed)
            //        {
            //            map.tileArray[(int)currentTile.Y * map.Width + (int)currentTile.X] = new MapTile(tileIndexToCreate, specialIndexToCreate);
            //            //clickedTiles.Add(parser.Tiles[map.TileArray[(int)currentTile.Y * map.Width + (int)currentTile.X].tileIndex]);
            //        }
            //            Window.Title = currentTile.ToString() + " Tile Index " + map.TileArray[(int)currentTile.Y * map.Width + (int)currentTile.X].tileIndex.ToString() + " Special Index " + map.TileArray[(int)currentTile.Y * map.Width + (int)currentTile.X].specialIndex.ToString() + " " + r16Parser.Tiles[map.TileArray[(int)currentTile.Y * map.Width + (int)currentTile.X].tileIndex].header.Count;                   
            //    }
            //    else
            //    {
            //        Window.Title = "N/A";
            //    }
            //}
            //else
            //{
            //    Window.Title = "Not Active";
            //}
            
            // TODO: Add your update logic here
            lastMouseState = Mouse.GetState();
            base.Update(gameTime);
        }

        /// <summary>
        /// This is called when the game should draw itself.
        /// </summary>
        /// <param name="gameTime">Provides a snapshot of timing values.</param>
        protected override void Draw(GameTime gameTime)
        {
            graphics.GraphicsDevice.Clear(Color.CornflowerBlue);

            Vector2 currentMousePos = new Vector2(Mouse.GetState().X, Mouse.GetState().Y) - offset;

            Vector2 currentTile = new Vector2((float)Math.Floor(currentMousePos.X / 32 / scale), (float)Math.Floor(currentMousePos.Y / 32 / scale));

            if (currentTile.X >= 0 && currentTile.X < 20
                && currentTile.Y >= 0 && currentTile.Y < 40)
            {
                Window.Title = currentTile.ToString();

                for (int i = 0; i < 8; i++)
                {
                    Window.Title += ", " + dataFile.TileData[(int)currentTile.X + (int)currentTile.Y * 20, i].ToString();
                }
            }
            else
            {
                Window.Title = currentTile.ToString() + "   " + "-";
            }

            // TODO: Add your drawing code here
            spriteBatch.Begin();
            for (int x = 0; x < 20; x++)
            {
                for (int y = 0; y < 40; y++)
                {
                    if (y * 20 + x < 800)
                    {
                        //if(y * 20 + x < 256)
                        if(Keyboard.GetState().IsKeyDown(Keys.Space))
                            spriteBatch.Draw(r8Parser.Tiles[y * 20 + x].texture, new Vector2(x * 32, y * 32) + offset, Color.White);
                        else
                            spriteBatch.Draw(r16Parser.Tiles[y * 20 + x].texture, new Vector2(x * 32, y * 32) + offset, Color.White);

                            //spriteBatch.DrawString(arial, dataFile.TileData[y * 20 + x,0].ToString(), new Vector2(x * 32, y * 32) + offset, Color.Black);
                        //[(int)currentTile.X + (int)currentTile.Y * 20
//                        else
  //                          spriteBatch.Draw(r16Parser.Tiles[y * 20 + x].texture, new Vector2(x * 32, y * 32), Color.Red);
                    }
                }
            }

            /*
            
            Color drawColor = Color.White;
            for (int x = (int)(offset.X/32.0f); x < map.Width; x++)
            {
                for (int y = 0; y < map.Height; y++)
                {
                    Vector2 position = new Vector2(x * 32 * scale, y * 32 * scale) + offset;
                    if (position.X > -32 && position.X < graphics.PreferredBackBufferWidth + 32 && position.Y > -32 && position.Y < graphics.PreferredBackBufferHeight + 32)
                    {
                        if (map.TileArray[y * map.Width + x].tileIndex < 800)
                        {


                            switch (map.TileArray[y * map.Width + x].specialIndex)
                            {
                                case 1:
                                    drawColor = Color.Red;
                                    break;
                                case 2:
                                    drawColor = Color.Blue;
                                    break;
                                case 20:
                                    drawColor = Color.Lime;
                                    break;
                                case 23:
                                    drawColor = Color.Navy;
                                    break;
                                case 45:
                                    drawColor = Color.Yellow;
                                    break;
                                default:
                                    if (map.TileArray[y * map.Width + x].specialIndex > 0)
                                    {
                                        drawColor = Color.Cyan;
                                    }
                                    else
                                    {
                                        drawColor = Color.White;
                                    }

                                    break;
                            }
                            spriteBatch.Draw(r16Parser.Tiles[map.TileArray[y * map.Width + x].tileIndex].texture, new Vector2(x * 32 * scale, y * 32 * scale) + offset, null, drawColor, 0, new Vector2(0), scale, SpriteEffects.None, 0);
                            spriteBatch.DrawString(arial, map.TileArray[y * map.Width + x].specialIndex.ToString(), new Vector2(x * 32 * scale, y * 32 * scale) + offset, Color.Black);
                        }
                    }

                }
            }*/
            spriteBatch.End();
            base.Draw(gameTime);
        }
    }
}
